package city.spring.service;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.service.IService;

import java.io.Serializable;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 基础 Service 对象
 *
 * @author HouKunLin
 * @date 2020/7/22 0022 16:52
 */
public interface BaseService<MAPPER extends BaseMapper<ENTITY>, ENTITY> extends IService<ENTITY> {
    /**
     * 查询（根据ID 批量查询），从 records 记录中获取到 id 列表，通过 getRecordEntityIdFunction 方法获取 id 字段信息
     *
     * @param records                   含有当前对象关联字段的列表对象
     * @param getRecordEntityIdFunction 从records记录对象中获取当前实体类的关联主键ID
     * @param <RECORD>                  记录对象
     * @return 查询结果
     * @see #listByIds(Collection)
     */
    default <RECORD> List<ENTITY> listByIds(Collection<RECORD> records,
                                            Function<RECORD, ? extends Serializable> getRecordEntityIdFunction) {
        Set<? extends Serializable> idSet = records.stream().map(getRecordEntityIdFunction).collect(Collectors.toSet());
        if (idSet.isEmpty()) {
            return Collections.emptyList();
        }
        return listByIds(idSet);
    }

    /**
     * 查询（根据ID 批量查询），从 records 记录中获取到 id 列表，通过 getRecordEntityIdFunction 方法获取 id 字段信息。
     *
     * @param records                   含有当前对象关联字段的列表对象
     * @param getRecordEntityIdFunction 从records记录对象中获取当前实体类的关联主键ID
     * @param getEntityIdFunction       获取实体类的主键ID
     * @param <RECORD>                  记录对象
     * @param <ENTITY_KEY>              实体类主键字段类型
     * @return 查询结果，通过 getEntityIdFunction 获取 map 的 key 值
     * @see #listByIds(Collection)
     */
    default <RECORD, ENTITY_KEY> Map<ENTITY_KEY, ENTITY> listByIds(Collection<RECORD> records,
                                                                   Function<RECORD, ? extends Serializable> getRecordEntityIdFunction,
                                                                   Function<ENTITY, ENTITY_KEY> getEntityIdFunction) {
        Set<? extends Serializable> idSet = records.stream().map(getRecordEntityIdFunction).collect(Collectors.toSet());
        if (idSet.isEmpty()) {
            return Collections.emptyMap();
        }
        return listByIds(idSet).stream().collect(Collectors.toMap(getEntityIdFunction, Function.identity()));
    }

    /**
     * 查询（根据 columnMap 条件）
     *
     * @param columnMap           columnMap 表字段 map 对象
     * @param getEntityIdFunction 获取实体类的主键ID
     * @param <ENTITY_KEY>        实体类主键字段类型
     * @return 查询结果，通过 getEntityIdFunction 获取 map 的 key 值
     * @see #listByMap(Map)
     */
    default <ENTITY_KEY> Map<ENTITY_KEY, ENTITY> listByMap(Map<String, Object> columnMap, Function<ENTITY, ENTITY_KEY> getEntityIdFunction) {
        return listByMap(columnMap).stream().collect(Collectors.toMap(getEntityIdFunction, Function.identity()));
    }

    /**
     * 查询列表
     *
     * @param queryWrapper        queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
     * @param getEntityIdFunction 获取实体类的主键ID
     * @param <ENTITY_KEY>        实体类主键字段类型
     * @return 查询结果，通过 getEntityIdFunction 获取 map 的 key 值
     * @see #list(Wrapper)
     */
    default <ENTITY_KEY> Map<ENTITY_KEY, ENTITY> list(Wrapper<ENTITY> queryWrapper, Function<ENTITY, ENTITY_KEY> getEntityIdFunction) {
        return list(queryWrapper).stream().collect(Collectors.toMap(getEntityIdFunction, Function.identity()));
    }

    /**
     * 查询列表
     *
     * @param getEntityIdFunction 获取实体类的主键ID
     * @param <ENTITY_KEY>        实体类主键字段类型
     * @return 查询结果，通过 getEntityIdFunction 获取 map 的 key 值
     * @see #list()
     */
    default <ENTITY_KEY> Map<ENTITY_KEY, ENTITY> list(Function<ENTITY, ENTITY_KEY> getEntityIdFunction) {
        return list().stream().collect(Collectors.toMap(getEntityIdFunction, Function.identity()));
    }

    /**
     * 查询列表
     *
     * @param queryWrapper        实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
     * @param getEntityIdFunction 获取实体类的主键ID
     * @param <ENTITY_KEY>        实体类主键字段类型
     * @return 查询结果，通过 getEntityIdFunction 获取 map 的 key 值
     * @see #listMaps(Wrapper)
     */
    default <ENTITY_KEY> Map<ENTITY_KEY, Map<String, Object>> listMaps(Wrapper<ENTITY> queryWrapper, Function<Object, ENTITY_KEY> getEntityIdFunction) {
        return listMaps(queryWrapper).stream().collect(Collectors.toMap(getEntityIdFunction, Function.identity()));
    }

    /**
     * 查询所有列表
     *
     * @param getEntityIdFunction 获取实体类的主键ID
     * @param <ENTITY_KEY>        实体类主键字段类型
     * @return 查询结果，通过 getEntityIdFunction 获取 map 的 key 值
     * @see #listMaps()
     */
    default <ENTITY_KEY> Map<ENTITY_KEY, Map<String, Object>> listMaps(Function<Object, ENTITY_KEY> getEntityIdFunction) {
        return listMaps().stream().collect(Collectors.toMap(getEntityIdFunction, Function.identity()));
    }
}
